package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 张杰
 * Date: 2022-04-21
 * Time: 19:23
 */
//站在服务器的角度:
//1.源IP: 服务器本机的IP
//2.源端口: 服务器绑定的端口 (此处手动指定9090)
//3.目的IP: 包含在收到的数据报中(客户端的IP)
//4.目的端口: 包含在收到的数据报中.(客户端的端口)
//5.协议类型: UDP
public class UdpEchoServer {
    // 进行网络编程,第一步就需要先准备好socket实例,这是进行网络编程的前提
   private DatagramSocket socket = null;

    //构造服务器的socket对象的时候,需要显式的绑定一个端口号
    //端口号用来区分应用程序,主机收到网卡上的数据知道该数据应该给哪个程序
    //构造socket对象可能失败的原因:1.端口号被占了,同一个主机的两个程序不能有相同的端口号
    // 2.每个进程能够打开的文件个数是有上限的.如果进城之前已经打开过很多文件了,此处的socket文件就不能顺利打开了
    public UdpEchoServer(int port) throws SocketException {
       socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("启动服务器!");
        //UDP不需要建立连接,直接接收从客户端来的数据
        while (true){
            //1.读取客户端发来的请求
            DatagramPacket requestPacket = new DatagramPacket(new byte[1024],1024);
            socket.receive(requestPacket);//为了接收数据,创建一个空的DatagramPacket对象
            //把DatagramPacket解析成一个String
            String request = new String(requestPacket.getData(),0,requestPacket.getLength(),"UTF-8");
            //2.根据客户端请求计算响应(由于是回显服务,省略)
            String response = process(request);
            //3.把响应写回到客户端
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            System.out.printf("[%s:%d] req: %s, resp: %s\n",
                    requestPacket.getAddress().toString(), requestPacket.getPort(), request, response);
        }
    }

    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}
